home *** CD-ROM | disk | FTP | other *** search
- Subject: v14i086: Sun rasterfile I/O library
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: Marc Majka <majka@grads.cs.ubc.cdn>
- Posting-number: Volume 14, Issue 86
- Archive-name: rast
-
- Here is a set of library subroutines which I have found useful for reading
- and writing SUN rasterfiles. The package contains all the usual stuff:
- README, Makefile, sources, manuals, and a couple of sample programs.
-
- I have tested and debugged the library to some extent, but local hardware
- limitations precluded my from giving them a vigorous workout. There may
- be bugs. If you find or fix any, please let me know!
-
- ---
- Marc Majka
-
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create the files:
- # README
- # Makefile
- # rast.c
- # rast.h
- # rast.3
- # rdemo.c
- # rsee.c
- export PATH; PATH=/bin:$PATH
- if test -f 'README'
- then
- echo shar: will not over-write existing file "'README'"
- else
- cat << \SHAR_EOF > 'README'
- This package contains a library of routines for reading and writing
- SUN rasterfiles in a pixel-at-a-time manner. The routines maintain
- a data structure called a RASTER, which contains all the usual file
- header information from a rasterfile, along with a file pointer and
- a memory cache of a single line (row) of the rasterfile.
-
- Bit stuffing and unpacking is accomplished with pixrect operations,
- which are about as fast as possible.
-
- Manifest:
-
- rast.h - header file to include
- rast.c - library source
- rast.3 - manual entry
- rdemo.c - demo program
- rsee.c - program to print rasterfile headers
- Makefile - to compile it all
-
- Note that, since the library pixrect operations, you must include
- -lpixrect in any programs which use the library.
-
- ---
- Marc Majka - UBC Laboratory for Computational Vision
-
- <majka@vision.ubc.cdn>
- <majka@ubc.bitnet>
- <majka@ubc-vision.uucp>
-
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'Makefile'
- then
- echo shar: will not over-write existing file "'Makefile'"
- else
- cat << \SHAR_EOF > 'Makefile'
- all: rast.o rdemo rsee
-
- rast.o: rast.c rast.h
- cc -c rast.c
-
- rdemo: rdemo.c rast.o
- cc -o rdemo rdemo.c rast.o -lpixrect
-
- rsee: rsee.c rast.o
- cc -o rsee rsee.c rast.o -lpixrect
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'rast.c'
- then
- echo shar: will not over-write existing file "'rast.c'"
- else
- cat << \SHAR_EOF > 'rast.c'
- #include "rast.h"
-
- RASTER *Ropen(f,m)
- char *f;
- int m;
- {
- RASTER *im, *Ropen_read(), *Ropen_write();
-
- im = NULL;
- if (m == R) im = Ropen_read(f);
- if (m == W) im = Ropen_write(f);
- return(im);
- }
-
- RASTER *Rdopen(f,m)
- int f,m;
- {
- RASTER *im, *Rdopen_stdin(), *Rdopen_stdout();
-
- im = NULL;
- if (f == 0 && m == R) im = Rdopen_stdin();
- if (f == 1 && m == W) im = Rdopen_stdout();
- return(im);
- }
-
- RASTER *Ropen_read(f)
- char *f;
- {
- RASTER *im;
- char *malloc();
-
- im = (RASTER *)malloc(sizeof(RASTER));
- im->fp = fopen(f,"r");
- im->mode = R;
- if (im->fp == NULL) {
- fprintf(stderr,"read open fails for file \"%s\"!\n",f);
- im = NULL;
- return(im);
- }
- return(im);
- }
-
- RASTER *Rdopen_stdin()
- {
- RASTER *im;
- char *malloc();
-
- im = (RASTER *)malloc(sizeof(RASTER));
- im->fp = stdin;
- im->mode = R;
- if (im->fp == NULL) {
- fprintf(stderr,"read open fails for stdin!\n");
- im = NULL;
- return(im);
- }
- return(im);
- }
-
- RASTER *Ropen_write(f)
- char *f;
- {
- RASTER *im;
- char *malloc();
-
- im = (RASTER *)malloc(sizeof(RASTER));
- im->fp = fopen(f,"w");
- if (im->fp == NULL) {
- fprintf(stderr,"write open fails for file \"%s\"!\n",f);
- im = NULL;
- return(im);
- }
-
- im->mode = W;
- im->width = 0;
- im->height = 0;
- im->depth = 0;
- im->maplength = 0;
- im->maptype = RMT_NONE;
-
- if (im->fp == NULL) im = NULL;
- return(im);
- }
-
- RASTER *Rdopen_stdout()
- {
- RASTER *im;
- char *malloc();
-
- im = (RASTER *)malloc(sizeof(RASTER));
- im->fp = stdout;
- if (im->fp == NULL) {
- fprintf(stderr,"write open fails for stdout!\n");
- im = NULL;
- return(im);
- }
-
- im->mode = W;
- im->width = 0;
- im->height = 0;
- im->depth = 0;
- im->maplength = 0;
- im->maptype = RMT_NONE;
-
- return(im);
- }
-
- Rgetheader(im)
- RASTER *im;
- {
- char *malloc();
- int i, rc, ll, extra;
- struct rasterfile rhead;
-
- rc = fread(&rhead,(sizeof (struct rasterfile)),1,im->fp);
-
- if (rc <= 0) {
- fprintf(stderr,"Rgetheader failed!\n");
- return(0);
- }
- if (rhead.ras_magic != RAS_MAGIC) return(0);
-
- im->height = rhead.ras_height;
- im->width = rhead.ras_width;
- im->depth = rhead.ras_depth;
- im->length = rhead.ras_length;
- im->type = rhead.ras_type;
- im->maptype = rhead.ras_maptype;
- im->maplength = rhead.ras_maplength;
-
- extra = (16 - ((im->width * im->depth) % 16)) % 16;
- ll = ((im->width * im->depth) + extra) / 8;
-
- im->linelen = ll;
- im->cache = malloc(ll);
- im->c_pixel = im->width + 1;
- im->c_pr = mem_point(im->width,1,im->depth,im->cache);
- if (im->maplength > 0) {
- im->map = malloc(im->maplength);
- for (i = 0; i < im->maplength; i++) im->map[i] = getc(im->fp);
- }
- return(1);
- }
-
- Rputheader(im)
- RASTER *im;
- {
- char *malloc();
- int i, rc, ll, extra;
- struct rasterfile rhead;
-
- extra = (16 - ((im->width * im->depth) % 16)) % 16;
- ll = ((im->width * im->depth) + extra) / 8;
-
- if (im->width == 0) {
- fprintf(stderr,"rasterfile width is zero!\n");
- return(0);
- }
- if (im->height == 0) {
- fprintf(stderr,"rasterfile height is zero!\n");
- return(0);
- }
- if (im->depth == 0) {
- fprintf(stderr,"rasterfile depth is zero!\n");
- return(0);
- }
-
- rhead.ras_magic = RAS_MAGIC;
- rhead.ras_width = im->width;
- rhead.ras_height = im->height;
- rhead.ras_depth = im->depth;
- rhead.ras_length = ll * im->height;
- rhead.ras_type = RT_STANDARD;
- rhead.ras_maptype = im->maptype;
- rhead.ras_maplength = im->maplength;
-
- im->linelen = ll;
- im->cache = malloc(ll);
- im->c_pixel = 0;
- im->c_pr = mem_point(im->width,1,im->depth,im->cache);
-
- rc = fwrite(&rhead,(sizeof (struct rasterfile)),1,im->fp);
-
- if (rc <= 0) {
- fprintf(stderr,"Rputheader failed!\n");
- return(0);
- }
-
- if (im->maptype != RMT_NONE && im->maplength > 0)
- fwrite(im->map,im->maplength,1,im->fp);
- return(1);
- }
-
- Rgetpix(im)
- RASTER *im;
- {
- int pix;
-
- if (im->mode != R) {
- fprintf(stderr,"attempt to read rasterfile opened for write!\n");
- return(-1);
- }
-
- if (im->c_pixel >= im->width) {
- fread(im->cache,im->linelen,1,im->fp);
- im->c_pixel = 0;
- }
-
- pix = pr_get(im->c_pr,im->c_pixel,0);
- im->c_pixel++;
- return(pix);
- }
-
- Rputpix(im,pix)
- RASTER *im;
- int pix;
- {
- if (im->mode != W) {
- fprintf(stderr,"attempt to write rasterfile opened for read!\n");
- return(-1);
- }
-
- pr_put(im->c_pr,im->c_pixel,0,pix);
- im->c_pixel++;
-
- if (im->c_pixel >= im->width) {
- fwrite(im->cache,im->linelen,1,im->fp);
- im->c_pixel = 0;
- }
- }
-
- Rclose(im)
- RASTER *im;
- {
- if (im->mode == W) fflush(im->fp);
- fclose(im->fp);
- }
-
- Rinfo(im)
- RASTER *im;
- {
- fprintf(stderr," height = %d\n",im->height);
- fprintf(stderr," width = %d\n",im->width);
- fprintf(stderr," depth = %d\n",im->depth);
- fprintf(stderr," length = %d\n",im->length);
- fprintf(stderr," type = %d\n",im->type);
- fprintf(stderr," maptype = %d\n",im->maptype);
- fprintf(stderr," maplength = %d\n",im->maplength);
- }
-
- Rinitmap(im,t,l)
- RASTER *im;
- int t,l;
- {
- char *malloc();
-
- im->maptype = t;
- im->maplength = l;
- im->map = malloc(l);
- }
-
- Rputmap(im,i,r,g,b)
- RASTER *im;
- int i,r,g,b;
- {
- int x;
-
- switch (im->maptype) {
- case RMT_NONE:
- fprintf(stderr,"can't put in a null map!\n");
- break;
- case RMT_RAW:
- im->map[i] = r;
- break;
- case RMT_EQUAL_RGB:
- x = i * 3;
- im->map[x++] = r;
- im->map[x++] = g;
- im->map[x] = b;
- break;
- default:
- fprintf(stderr,"unknown map type in rasterfile!\n");
- }
- }
-
- Rgetmap(im,i,r,g,b)
- RASTER *im;
- int i,*r,*g,*b;
- {
- int x;
-
- switch (im->maptype) {
- case RMT_NONE:
- fprintf(stderr,"can't get from a null map!\n");
- break;
- case RMT_RAW:
- *r = im->map[i];
- break;
- case RMT_EQUAL_RGB:
- x = i * 3;
- *r = im->map[x++];
- *g = im->map[x++];
- *b = im->map[x];
- break;
- default:
- fprintf(stderr,"unknown map type in rasterfile!\n");
- }
- }
-
- Rgetmappedpix(im,r,g,b)
- RASTER *im;
- int *r,*g,*b;
- {
- int pix, x;
-
- if (im->mode != R) {
- fprintf(stderr,"attempt to read rasterfile opened for write!\n");
- return(-1);
- }
-
- if (im->c_pixel >= im->width) {
- fread(im->cache,im->linelen,1,im->fp);
- im->c_pixel = 0;
- }
-
- pix = pr_get(im->c_pr,im->c_pixel,0);
- im->c_pixel++;
-
- switch (im->maptype) {
- case RMT_RAW:
- *r = im->map[pix];
- break;
- case RMT_EQUAL_RGB:
- x = pix * 3;
- *r = im->map[x++];
- *g = im->map[x++];
- *b = im->map[x];
- break;
- default:
- *r = pix;
- break;
- }
- }
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'rast.h'
- then
- echo shar: will not over-write existing file "'rast.h'"
- else
- cat << \SHAR_EOF > 'rast.h'
- #include <stdio.h>
- #include <pixrect/pixrect_hs.h>
-
- #define R 0
- #define W 1
-
- typedef struct RASTER_STRUCT {
- int height; /* number of rows */
- int width; /* number of columns */
- int depth; /* bits per pixel */
- int length; /* bytes of data following header */
- int type; /* rasterfile type */
- int maptype; /* type of lookup table */
- int maplength; /* length of lookup table */
- char *map; /* lookup table */
- int linelen; /* bytes in a row (padded to even 16 bits) */
- FILE *fp; /* file pointer */
- int mode; /* read (R) or write (W) mode flag */
- char *cache; /* cache of 1 row */
- int c_pixel; /* current pixel in row cache */
- struct pixrect *c_pr; /* make cache look like a pixrect */
- } RASTER;
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'rast.3'
- then
- echo shar: will not over-write existing file "'rast.3'"
- else
- cat << \SHAR_EOF > 'rast.3'
- .TH RAST 3
- .SH NAME
- rast - SUN rasterfile interface
- .SH SYNOPSIS
- .B #include \*(lqrast.h\*(rq
- .sp
- .B RASTER *Ropen(filename,mode)
- .br
- .B char *filename;
- .br
- .B int mode;
- .sp
- .B RASTER Rdopen(filedes,mode)
- .br
- .B int filedes, mode;
- .sp
- .B Rgetheader(raster)
- .br
- .B RASTER *raster;
- .sp
- .B Rputheader(raster)
- .br
- .B RASTER *raster;
- .sp
- .B Rgetpix(raster)
- .br
- .B RASTER *raster;
- .sp
- .B Rputpix(raster,pixel)
- .br
- .B RASTER *raster;
- .br
- .B int pixel;
- .sp
- .B Rgetmappedpix(raster,value)
- .br
- .B RASTER *raster;
- .br
- .B int *value;
- .sp
- .B Rgetmappedpix(raster,red,green,blue)
- .br
- .B RASTER *raster;
- .br
- .B int *red, *green, *blue;
- .sp
- .B Rinitmap(raster,type,length)
- .br
- .B RASTER *raster;
- .br
- .B int type, length;
- .sp
- .B Rputmap(raster,index,value)
- .br
- .B RASTER *raster;
- .br
- .B int index, value;
- .sp
- .B Rputmap(raster,index,red,green,blue)
- .br
- .B RASTER *raster;
- .br
- .B int index, red, green, blue;
- .sp
- .B Rgetmap(raster,index,value)
- .br
- .B RASTER *raster;
- .br
- .B int index, *value;
- .sp
- .B Rgetmap(raster,index,red,green,blue)
- .br
- .B RASTER *raster;
- .br
- .B int index, *red, *green, *blue;
- .sp
- .B Rclose(raster)
- .br
- .B RASTER *raster;
- .sp
- .SH DESCRIPTION
- This library provides pixel I/O for SUN rasterfiles.
- .sp
- .I Ropen
- opens a SUN rasterfile for reading or writing, and returns a RASTER
- structure. The mode should be R for read, W for write. R and W are
- defined in the file rast.h.
- .I Rdopen
- opens a stream, specified by a UNIX file descriptor. The RASTER structure
- is defined below.
- .sp
- After a rasterfile has been opened to read, data from the rasterfile
- header is fetched and placed in the RASTER structure with a call to
- .I Rgetheader.
- A rasterfile opened for output must have (at least) it's width, height, and
- depth set before the header may be written with
- .I Rputheader.
- If the header is to include a map, the map must be initialized with a call to
- .I Rinitmap.
- Map values may be set directly in the RASTER structure, or they my be set
- using
- .I Rputmap.
- The map type must be one defined in the include file <rasterfile.h>.
- .sp
- For convenience, map values may be retrieved with
- .I Rgetmap.
- .sp
- Each call to
- .I Rgetpix
- will return a raw pixel value from the rasterfile.
- .I Rgetmappedpix
- returns the result of putting the raw pixel value through the rasterfile map.
- .I Rputpix
- writes pixel values to the rasterfile.
- .sp
- A rasterfile is closed with
- .I Rclose.
- .SH "RASTER STRUCTURE"
- The data structure maintained by these routines is defined in the file rast.h.
- .sp
- .nf
- typedef struct RASTER_STRUCT {
- int height; /* number of rows */
- int width; /* number of columns */
- int depth; /* bits per pixel */
- int length; /* bytes of data following header */
- int type; /* rasterfile type */
- int maptype; /* type of lookup table */
- int maplength; /* length of lookup table */
- char *map; /* lookup table */
- int linelen; /* bytes in a row (padded to even 16 bits) */
- FILE *fp; /* file pointer */
- int mode; /* read (R) or write (W) mode flag */
- char *cache; /* cache of 1 row */
- int c_pixel; /* current pixel in row cache */
- struct pixrect *c_pr; /* make cache look like a pixrect */
- } RASTER;
- .fi
- .sp
- The height, width, depth, length, type, maptype, and maplength fields
- have exactly the same meaning as they do in rasterfiles. The map field
- is used to store the rasterfile map data.
- .sp
- The linelen field gives the number of bytes in a single line (row)
- in the rasterfile. This is different from the width because each line
- is padded with zero bits to make it an integer multiple of 16 bits in length.
- .sp
- The UNIX file pointer is kept in the fp field, and a read/write flag is
- kept in the mode field.
- .sp
- Pixels are stored in the cache field, which holds one line (row) of the
- raster. The cache is maintained by
- .I Rgetpix
- and
- .I Rputpix.
- The current pixel (column) within the cache is recorded by in the c_pixel
- field. The cache is efficiently accessed by turning it into a memory pixrect
- and using
- .I pr_get
- and
- .I pr_put
- to do the necessary bit stuffing. The memory pixrect is kept in the c_pr
- field. Because of this, programs using this library must be compiled with
- -lpixrect.
- .SH AUTHOR
- Marc Majka
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'rdemo.c'
- then
- echo shar: will not over-write existing file "'rdemo.c'"
- else
- cat << \SHAR_EOF > 'rdemo.c'
- /***********************************************************************
-
- rdemo - reads a rasterfile, computes the average of the colour
- values (if applicable) of the pixels, and writes a new rasterfile
- with the average. An inverting colour map is added.
-
- ***********************************************************************/
-
- #include <stdio.h>
- #include "rast.h"
-
- main(argc,argv)
- int argc;
- char *argv[];
- {
- int r, g, b, avg, row, col, i, pix, ifile, ofile;
- RASTER *irast, *orast, *Ropen(), *Rdopen();
-
- ifile = 0;
- ofile = 0;
-
- for (i = 1; i < argc; i++) {
- if (argv[i][0] == '-') {
- switch (argv[i][1]) {
- case 'i': ifile = ++i; break;
- case 'o': ofile = ++i; break;
- default: usage();
- }
- }
- }
-
- if (ifile) irast = Ropen(argv[ifile],R);
- else irast = Rdopen(0,R);
- if (irast == NULL) {
- fprintf(stderr,"rdemo: input rasterfile open failed!\n");
- exit(1);
- }
-
- if (ofile) orast = Ropen(argv[ofile],W);
- else orast = Rdopen(1,W);
- if (irast == NULL) {
- fprintf(stderr,"rdemo: output rasterfile open failed!\n");
- exit(1);
- }
-
- if (!Rgetheader(irast)) {
- fprintf(stderr,"input file is not a raster file!\n");
- exit(1);
- }
-
- orast->height = irast->height;
- orast->width = irast->width;
- orast->depth = irast->depth;
-
- Rinitmap(orast,RMT_EQUAL_RGB,256*3);
- for (i = 0; i < 256; i++) Rputmap(orast,255-i,i,i,i);
-
- Rputheader(orast);
-
- if (irast->maptype == RMT_EQUAL_RGB) {
- for (row = 0; row < irast->height; row++)
- for (col = 0; col < irast->width; col++) {
- Rgetmappedpix(irast,&r,&g,&b);
- avg = (r + g + b) / 3;
- Rputpix(orast,avg);
- }
- }
- else if (irast->maptype == RMT_RAW) {
- for (row = 0; row < irast->height; row++)
- for (col = 0; col < irast->width; col++) {
- Rgetmappedpix(irast,&pix);
- Rputpix(orast,pix);
- }
- }
- else if (irast->maptype == RMT_NONE) {
- for (row = 0; row < irast->height; row++)
- for (col = 0; col < irast->width; col++) {
- pix = Rgetpix(irast);
- Rputpix(orast,pix);
- }
- }
- else {
- fprintf(stderr,"rdemo: unknown map type in input rasterfile!\n");
- exit(1);
- }
-
- Rclose(irast);
- Rclose(orast);
- }
-
- usage()
- {
- fprintf(stderr,"usage: rdemo [-i file] [-o file]\n");
- fprintf(stderr," -i input rasterfile [default is stdin]\n");
- fprintf(stderr," -o output rasterfile [default is stdout]\n");
- exit(0);
- }
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'rsee.c'
- then
- echo shar: will not over-write existing file "'rsee.c'"
- else
- cat << \SHAR_EOF > 'rsee.c'
- #include <stdio.h>
- #include "rast.h"
-
- main(argc,argv)
- int argc;
- char *argv[];
- {
- RASTER *irast, *Ropen();
- int i, rc;
-
- for (i = 1; i < argc; i++) {
- irast = Ropen(argv[i],R);
- if (irast == NULL)
- fprintf(stderr,"rasterfile open failed for \"%s\"!\n",argv[i]);
- else {
- rc = Rgetheader(irast);
- fprintf(stderr,"%s:\n",argv[i]);
- if (rc) Rinfo(irast);
- else fprintf(stderr,"not a rasterfile!\n");
- fprintf(stderr,"\n");
- Rclose(irast);
- }
- }
- exit(0);
- }
- SHAR_EOF
- fi # end of overwriting check
- # End of shell archive
- exit 0
-
-
-